package org.yelongframework.yaml;

import java.util.LinkedHashMap;
import java.util.Map;

import org.yelongframework.core.util.MapWrapper;
import org.yelongframework.lang.Nullable;

/**
 * yaml映射默认实现
 * 
 * @since 1.0.0
 */
public class DefaultYamlMap extends MapWrapper<String, Object> implements YamlMap {

	private static final long serialVersionUID = 8370336285290591442L;

	public DefaultYamlMap() {
	}

	public DefaultYamlMap(Map<String, Object> map) {
		super(map);
	}

	@Override
	public String getString(String key) {
		Object value = getObject(key);
		return value == null ? null : value.toString();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Object getObject(String key) {
		String[] keys = key.split("[.]");
		Map<String, Object> currentMap = getSourceMap();
		for (int i = 0; i < keys.length; i++) {
			String k = keys[i];
			Object v = currentMap.get(k);
			if (v == null) {
				return null;
			}
			// 最后一个节点直接返回
			if (i == keys.length - 1) {
				return v;
			}
			// 如果值是map则继续获取
			if (v instanceof Map) {
				currentMap = (Map<String, Object>) v;
				continue;
			}
			// 不是最后一个节点且值不是map则返回null
			return null;
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Map<String, Object> getMap(String key) {
		Object value = getObject(key);
		if (value instanceof Map) {
			return (Map<String, Object>) value;
		}
		return null;
	}

	@Override
	public YamlMap getYamlMap(String key) {
		Map<String, Object> map = getMap(key);
		return null == map ? null : new DefaultYamlMap(map);
	}

	@Override
	public Map<String, Object> getProperties() {
		Map<String, Object> map = new LinkedHashMap<>();
		return toProperties(null, getSourceMap(), map);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	protected Map<String, Object> toProperties(@Nullable String prefix, Map<String, Object> map,
			Map<String, Object> properties) {
		map.forEach((k, v) -> {
			String cliedPrefix = prefix == null ? k : prefix + "." + k;
			if (v instanceof Map) {
				toProperties(cliedPrefix, (Map) v, properties);
			} else {
				properties.put(cliedPrefix, v);
			}
		});
		return properties;
	}

}
